require 'rubygems'
require 'eventmachine'
require 'net/dns/mdns-sd'
require 'base64'

$:.unshift File.join(File.dirname(__FILE__), *%w[..])
require 'jakl'

module JaklEventServer
  def post_init 
    @data = ''
  end
  
  def receive_data(data)
    @data << data
    if @data.scan(/;/).size == 3
      # B64 Encoded NAME;GROUP;MESSAGE;
      name, recv, message = data.split(';').map {|s| Base64.decode64(s) }
      Jakl::GrowlHandler.new.notify(recv, name, message)
      $stderr.puts "Name: #{name}, Recipient: #{recv}, Message: #{message}" if Jakl::Server.debug
    end
  end
end


module Jakl
  class Server
    DNSSD = Net::DNS::MDNSSD
    
    @@debug = false
    
    def self.debug=(value)
      @@debug = value
    end
    
    def self.debug
      @@debug
    end
      
    def initialize(options={})
      default_options = {
        :recvs => "jakl", 
        :timeout => 5, 
        :login => ENV['USER'],
        :port => 4180
      }
      @options = default_options.merge(options)
      
      # Add username to recvs
      @options[:recvs] = [@options[:recvs].split(',') << @options[:login]].join(',')
    end
        
    def start
      validate_login!
      
      EventMachine::run {
        EventMachine::start_server "0.0.0.0", @options[:port], JaklEventServer
        puts "Listening for howls on #{@options[:port]}"
      }
    end
    
    def validate_login!
      @start_time = Time.now.to_i
      
      
      DNSSD.register('jakl', '_jakl._tcp', 'local', @options[:port], 
                             {'recvs' => @options[:recvs], 'login' => @options[:login],
                              'start_time' => @start_time.to_s, 
                              'version' => Jakl::PROTOCOL_VERSION})
      
      num_matches = 0
      
      name_validation = DNSSD.resolve('jakl', '_jakl._tcp') do |r|
        if [r.text_record['login'], 
            r.text_record['recvs'].split(',')].flatten.include? @options[:login]
          num_matches += 1
          
          # If there are two people with my login, bail
          # In the race condition, both lose as there's 
          # no central metric for decision making
          if num_matches >= 2
            puts "The name #{@options[:login]} is already taken. Sorry :\\"
            exit 1
          end
        end
      end

      # Wait for resolv thread to come back
      sleep 3
      name_validation.stop
    end
  end
end


